﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;


public class Agent : MonoBehaviour {

	public bool sank { get; protected set; }
	public bool arrived { get; protected set; }

	protected Rigidbody2D _rigidBody;
	protected SpriteRenderer _agentSprite;
	protected int _obstacleLayer;
	protected int _finishPointLayer;
	protected int _wavePointLayer;
	protected List<Collider2D> _touchingWaves;

	public void Reset () {
		if (Application.isPlaying) {
			_rigidBody.velocity = Vector2.zero;
			_touchingWaves = new List<Collider2D>();

			_agentSprite.color = new Color(1f, 1f, 1f, 0f);
			_agentSprite.DOColor(Color.white, 2f);
		}
	}

	public void Sink () {
		if (sank == false && arrived == false) {
			sank = true;
			_rigidBody.simulated = false;

			_agentSprite.DOColor(new Color(0f, 0f, 1f, 0.5f), 1f);
			_agentSprite.sortingLayerName = "Background";
			_agentSprite.sortingOrder = 1;
		}
	}

	public void Arrived (FinishPoint point) {
		if (sank == false && arrived == false) {
			arrived = true;
			_rigidBody.simulated = false;

			transform.DOMove(point.transform.position, 1f).SetEase(Ease.OutCirc);
		}
	}

	void Awake () {
		_rigidBody = GetComponent<Rigidbody2D>();
		_agentSprite = GetComponentInChildren<SpriteRenderer>();

		_obstacleLayer = LayerMask.NameToLayer("Obstacle");
		_finishPointLayer = LayerMask.NameToLayer("FinishPoint");
		_wavePointLayer = LayerMask.NameToLayer("Wave");
	}

	void OnTriggerEnter2D (Collider2D other) {
		Log("TRIGGER ENTER " + other.gameObject.name);

		if (other.gameObject.layer == _obstacleLayer) {
			Sink();

			EventDispatchCenter.getInstance().dispatchEvent("level_fail", this);
		}

		if (other.gameObject.layer == _finishPointLayer) {
			Arrived(other.GetComponent<FinishPoint>());

			EventDispatchCenter.getInstance().dispatchEvent("level_success", this);
		}

		if (other.gameObject.layer == _wavePointLayer) {
			_touchingWaves.Add(other);
		}
	}

	void OnTriggerExit2D (Collider2D other) {
		Log("TRIGGER EXIT " + other.gameObject.name);

		if (other.gameObject.layer == _wavePointLayer) {
			_touchingWaves.Remove(other);
		}
	}

	void Update () {
		if (sank == false) {
			_agentSprite.transform.Rotate(Vector3.forward, 1f);
		}
	}

	void FixedUpdate () {
		if (GameController.getInstance().isPlaying && 
			sank == false && 
			arrived == false) {
			if (transform.position.x < -4f || transform.position.x > 4 ||
				transform.position.y < -5f || transform.position.y > 5) {
				EventDispatchCenter.getInstance().dispatchEvent("level_fail", this);

				Sink();
				return;
			}

			Vector2 velocity = Vector2.zero;

			for (int i = 0; i < GameController.getInstance().waves.Length; i++) {
				var wave = GameController.getInstance().waves[i];

				if (wave.waveing && 
//					_rigidBody.IsTouching(wave.waveCollider)) {
					_touchingWaves.Contains(wave.waveCollider)) {
					Vector3 dir3D = transform.position - wave.transform.position;
					Vector2 dir2D = new Vector2(dir3D.x, dir3D.y);

					velocity += dir2D.normalized * wave.GetForce();
				}
			}

			_rigidBody.velocity = velocity;
//			_rigidBody.MovePosition(_rigidBody.position + velocity * Time.fixedDeltaTime);
		}
	}

	protected static void Log(string message) {
		Debug.Log("<color=green>" + message + "</color>");
	}

}
